#ifndef PLIC_H
#define PLIC_H

#include "defs.h"

#define IRQN_MAX 66
#define PLIC_NUM_SOURCES (IRQN_MAX - 1)
#define PLIC_NUM_PRIORITIES 7

typedef struct _plic_source_priorities
{
    /* 0x0C000000: Reserved, 0x0C000004-0x0C000FFC: 1-1023 priorities */
    uint32_t priority[1024];
} __attribute__((packed, aligned(4))) plic_source_priorities_t;

typedef struct _plic_pending_bits
{
    /* 0x0C001000-0x0C00107C: Bit 0 is zero, Bits 1-1023 is pending bits */
    uint32_t u32[32];
    /* 0x0C001080-0x0C001FFF: Reserved */
    uint8_t resv[0xF80];
} __attribute__((packed, aligned(4))) plic_pending_bits_t;

typedef struct _plic_target_enables
{
    /* 0x0C002000-0x0C1F1F80: target 0-15871 enables */
    struct
        {
            uint32_t enable[32];/* Offset 0x00-0x7C: Bit 0 is zero, Bits 1-1023 is bits*/
        } target[15872];

        /* 0x0C1F2000-0x0C1FFFFC: Reserved, size 0xE000 */
        uint8_t resv[0xE000];
} __attribute__((packed, aligned(4))) plic_target_enables_t;

typedef struct _plic_target
{
    /* 0x0C200000-0x0FFFF004: target 0-15871 */
    struct {
        uint32_t priority_threshold;/* Offset 0x000 */
        uint32_t claim_complete;    /* Offset 0x004 */
        uint8_t resv[0xFF8];        /* Offset 0x008, Size 0xFF8 */
    } target[15872];
} __attribute__((packed, aligned(4))) plic_target_t;

typedef struct _plic {
    /* 0x0C000000-0x0C000FFC */
    plic_source_priorities_t source_priorities;
    /* 0x0C001000-0x0C001FFF */
    const plic_pending_bits_t pending_bits;
    /* 0x0C002000-0x0C1FFFFC */
    plic_target_enables_t target_enables;
    /* 0x0C200000-0x0FFFF004 */
    plic_target_t targets;
} __attribute__((packed, aligned(4))) plic_t;

extern volatile plic_t *const plic;

/* 
 * @brief Initialize PLIC external interrupt
 */
void interrupt_init(void);

#endif	/* PLIC_H */
